package cn.xiazhi.charging.order.service;

import cn.xiazhi.charging.common.ChargingConstant;
import cn.xiazhi.charging.common.JsonResult;
import cn.xiazhi.charging.common.MqttConstant;
import cn.xiazhi.charging.order.mqtt.MqttProducer;
import cn.xiazhi.charging.order.fegin.DeviceClient;
import cn.xiazhi.charging.order.fegin.UserClient;
import cn.xiazhi.charging.order.pojo.dto.ChargingDto;
import cn.xiazhi.charging.order.pojo.param.OrderAddParam;
import cn.xiazhi.charging.pojo.param.GunStatusUpdateParam;
import cn.xiazhi.charging.pojo.param.StationInfoVO;
import cn.xiazhi.charging.pojo.vo.UserInfoVO;
import cn.xiazhi.charging.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class OrderServiceImpl implements OrderService{
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private MqttProducer mqttProducer;

    /**
     * 创建订单
     * 1. 生成订单号
     * 2. 获取场站的信息和设备信息(服务之间的调用  订单服务调用设备服务)
     * 3. 获取用户信息(车辆信息) (服务之间调用 订单服务调用用户服务)
     * 4. 修改充电枪的状态 为 使用中 (服务之间的调用 订单服务调用设备服务)
     * 5. 给设备发送开始充电指令 (物联网 订单服务调用充电桩设备)
     * @param orderAddParam
     * @return
     */
    @Override
    public String createOrder(OrderAddParam orderAddParam) {
        log.info("业务层开始创建订单, orderAddParam: {}",orderAddParam);
        //1. 生成订单号
        String orderNo = getOrderNo();

        //2. 获取场站的信息和设备信息(服务之间的调用  订单服务调用设备服务)
        StationInfoVO stationInfoVO = getStationInfoByGunId(orderAddParam.getGunId());

        //3. 获取用户信息(车辆信息) (服务之间调用 订单服务调用用户服务)
        UserInfoVO userInfoVO = getUserInfoByUserId(orderAddParam.getUserId());

        //4. 修改充电枪的状态 为 使用中 (服务之间的调用 订单服务调用设备服务)
        boolean updateGunStatus = updaterGunStatusBusy(orderAddParam.getGunId());

        //5. 给设备发送开始充电指令 (物联网 订单服务调用充电桩设备)
        startCharging(orderNo, orderAddParam.getPileId(), orderAddParam.getGunId());

        return orderNo;
    }


    /**
     * 生成订单号
     * @return
     */
    private String getOrderNo() {
        return "666";
    }

    /**
     * 通过枪id获取场站信息
     * @param gunId
     * @return
     */
    private StationInfoVO getStationInfoByGunId(Integer gunId) {
        JsonResult<StationInfoVO> stationInfo = deviceClient.getStationInfo(gunId);
        if (stationInfo != null){
            return stationInfo.getData();
        }
        return null;
    }

    /**
     * 通过用户id获取用户信息
     * @param userId
     * @return
     */
    private UserInfoVO getUserInfoByUserId(Integer userId) {
        JsonResult<UserInfoVO> userCarInfo = userClient.getUserCarInfo(userId);
        if (userCarInfo != null){
            return userCarInfo.getData();
        }
        return null;
    }
    /**
     * 更新枪的状态为 使用中
     * @param gunId
     * @return
     */
    private boolean updaterGunStatusBusy(Integer gunId) {
        GunStatusUpdateParam gunStatusUpdateParam = new GunStatusUpdateParam();
        gunStatusUpdateParam.setGunId(gunId);
        gunStatusUpdateParam.setStatus(ChargingConstant.GUN_STATUS_BUSY);
        JsonResult<Boolean> gunStatusUpdate = deviceClient.updateGunStatus(gunStatusUpdateParam);
        if (gunStatusUpdate != null){
            return gunStatusUpdate.getData();
        }
        return false;
    }
    /**
     * 发送开始充电指令
     */
    private void startCharging(String orderNo,Integer pileId,Integer gunId) {
        //Topic 设计
        // 一种是枪的维度   或者 一种是桩的维度 消息体包含枪的信息
        // 从业务上讲都可以, 如果是枪的维度 topic的数量会比 桩的维度 的数量多
        // 占用更多的资源
        String topic = MqttConstant.TOPIC_START_CHARGING_PREFIX + pileId;

        //消息的设计
        //类似于接口的入参,思考业务如果缺少哪个入参,业务无法完成,这些入参是就是核心参数
        //首先得明确业务目标  给设备发送开始充电指令给一个用户的订单开始充电,
        // 参数应该包含 订单信息的唯一标识 订单id,设备信息,告诉具体哪个设备开始充电
        ChargingDto chargingDto = new ChargingDto();
        chargingDto.setOrderNo(orderNo);
        chargingDto.setGunId(gunId);
        chargingDto.setPileId(pileId);
        chargingDto.setMsg(ChargingConstant.START_CHARGING);
        log.debug("订单服务发送开始充电指令到设备:{},消息:{}",topic,chargingDto);
        //String string = chargingDto.toString();
        //消息体的序列化 Spring-boot 自动做的序列化 对象转json ,json转对象
        //需要我们手动序列化,不能toString ,应该把  对象转换为JSON
        //需要一个库 Jackson(Spring默认的) Gson     Spring-boot怎么干的?
        String json = JsonUtil.toJson(chargingDto);
        Boolean success = mqttProducer.publish(topic, json);
        log.debug("订单服务发送开始充电指令到设备:{},消息:{},结果:{}",topic,chargingDto,success);
        //如果发送失败,重试几次,如果实在不行通知用户,记录日志,接入告警系统

    }

}

























